﻿using System;
using System.Text;
using System.Reflection;
//using Microsoft.SharePoint;

namespace MagDev.Foundation
{    
    public class AppConfig
    {
        public class Attributes
        {
            public interface IAttribute<T>
            {
                T Value { get; }
            }
            public interface IAttributeGuid
            {
                Guid SiteColumnID { get; }
            }


            [AttributeUsage(AttributeTargets.Field)]
            public sealed class AppConfigModuleAttribute : Attribute, IAttribute<string>, IAttributeGuid
            {
                private readonly string value;

                public AppConfigModuleAttribute(string value)
                {
                    this.value = value;
                }

                public string Value
                {
                    get { return value; }
                }

                public Guid SiteColumnID
                {
                    get { return CoreColumnID.Module; }
                }
            }

            [AttributeUsage(AttributeTargets.Field)]
            public sealed class AppConfigGroupAttribute : Attribute, IAttribute<string>, IAttributeGuid
            {
                private readonly string value;

                public AppConfigGroupAttribute(string value)
                {
                    this.value = value;
                }

                public string Value
                {
                    get { return value; }
                }

                public Guid SiteColumnID
                {
                    get { return CoreColumnID.Group; }
                }
            }


            [AttributeUsage(AttributeTargets.Field)]
            public sealed class AppConfigKeyAttribute : Attribute, IAttribute<string>, IAttributeGuid
            {
                private readonly string value;

                public AppConfigKeyAttribute(string value)
                {
                    this.value = value;
                }

                public string Value
                {
                    get { return value; }
                }

                public Guid SiteColumnID
                {
                    get { return CoreColumnID.Key ; }
                }
            }

            [AttributeUsage(AttributeTargets.Field)]
            public sealed class AppConfigValueAttribute : Attribute, IAttribute<string>, IAttributeGuid
            {
                private readonly string value;

                public AppConfigValueAttribute(string value)
                {
                    this.value = value;
                }

                public string Value
                {
                    get { return value; }
                }

                public Guid SiteColumnID
                {
                    get { return CoreColumnID.Value ; }
                }
            }

            [AttributeUsage(AttributeTargets.Field)]
            public sealed class AppConfigActiveAttribute : Attribute, IAttribute<bool>, IAttributeGuid
            {
                private readonly bool value;

                public AppConfigActiveAttribute(bool value)
                {
                    this.value = value;
                }

                public bool Value
                {
                    get { return value; }
                }

                public Guid SiteColumnID
                {
                    get { return CoreColumnID.Active ; }
                }
            }                  


            public static R GetAttributeValue<T, R>(Enum @enum)
            {
                R attributeValue = default(R);

                if (@enum != null)
                {
                    FieldInfo fi = @enum.GetType().GetField(@enum.ToString());

                    if (fi != null)
                    {

                        T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[];

                        if (attributes != null && attributes.Length > 0)
                        {

                            IAttribute<R> attribute = attributes[0] as IAttribute<R>;
                            if (attribute != null)
                            {
                                attributeValue = attribute.Value;
                            }
                        }
                    }
                }

                return attributeValue;
            }

            public static Guid GetAttributeSiteColumn<T>(Enum @enum)
            {
                Guid siteColumnID = default(Guid);

                if (@enum != null)
                {
                    FieldInfo fi = @enum.GetType().GetField(@enum.ToString());

                    if (fi != null)
                    {

                        T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[];

                        if (attributes != null && attributes.Length > 0)
                        {

                            IAttributeGuid attribute = attributes[0] as IAttributeGuid;
                            if (attribute != null)
                            {
                                siteColumnID = attribute.SiteColumnID;
                            }
                        }
                    }
                }

                return siteColumnID;
            }
            

        }

        public class Helper
        {           
            /// <summary>
            /// Removes all items in the Module, Group, Key match.
            /// </summary>
            /// <param name="web"></param>
            /// <param name="acModule"></param>
            /// <param name="acGroup"></param>
            /// <param name="acKey"></param>
            //public void removeAppConfigItems(SPWeb web, string acModule, string acGroup, string acKey)
            //{                
            //    web.AllowUnsafeUpdates = true;
            //    try
            //    {
            //        // Get our list
            //        SPList list = web.Lists[Constants.AppConfigListName];
            //        // Setup our query 
            //        SPQuery itemsQuery = new SPQuery();                    
            //        itemsQuery.Query = CAMLQueries.GetAppConfigItems(acModule, acGroup, acKey);
            //        // Get Items that match
            //        SPListItemCollection listItems = list.GetItems(itemsQuery);

            //        // ensure we have items to delete
            //        if (listItems.Count > 0)
            //        {
            //            // build batch xml to delete all items at once - save performance and avoid list deletion iteration issues.
            //            StringBuilder sbDelete = new StringBuilder();
            //            sbDelete.Append(@"<?xml version=""1.0"" encoding=""UTF-8""?><Batch OnError=""Return"">");
            //            // build each item deletion command
            //            for (int index = 0; index < listItems.Count; index++)                    
            //            {
            //                sbDelete.AppendFormat(@"<Method ID=""{0}""><SetList Scope=""Request"">{1}</SetList><SetVar Name=""Cmd"">DELETE</SetVar><SetVar Name=""ID"">{2}</SetVar></Method>",
            //                                      index,
            //                                      list.ID,
            //                                      listItems[index].ID
            //                                      );
            //            }
            //            // close the batch
            //            sbDelete.Append(@"</Batch>");
            //            // execute
            //            string batchReturn = web.ProcessBatchData(sbDelete.ToString());
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        Logging.LogError(ex, Constants.standardsLog);                    
            //    }
            //    web.AllowUnsafeUpdates = false;
            //}


            /// <summary>
            /// Adds a single item specified to the AppConfig list
            /// </summary>
            /// <param name="web"></param>
            /// <param name="acModule"></param>
            /// <param name="acGroup"></param>
            /// <param name="acKey"></param>
            /// <param name="acValue"></param>
            /// <param name="acActive"></param>
            //public void addAppConfigItem(SPWeb web, string acModule, string acGroup, string acKey, string acValue, bool acActive)
            //{
            //    try
            //    {
            //        web.AllowUnsafeUpdates = true;
            //        SPList list = web.Lists[Constants.AppConfigListName];
            //        SPListItemCollection listItems = list.Items;
            //        // Create our new List Item now
            //        SPListItem listItem = listItems.Add();
            //        // setup Guid
            //        Guid attributeGuid = default(Guid);
            //        // Module Column
            //        attributeGuid = CoreColumnID.Module;
            //        listItem[attributeGuid] = acModule;
            //        // Group Column
            //        attributeGuid = CoreColumnID.Group;
            //        listItem[attributeGuid] = acGroup;
            //        // Key Column
            //        attributeGuid = CoreColumnID.Key;
            //        listItem[attributeGuid] = acKey;
            //        // Value Column
            //        attributeGuid = CoreColumnID.Value;
            //        listItem[attributeGuid] = acValue;
            //        // Active Column
            //        attributeGuid = CoreColumnID.Active;
            //        listItem[attributeGuid] = acActive;
            //        // update listitem and list
            //        listItem.Update();
            //        list.Update();
            //        // return web to normal
            //        web.AllowUnsafeUpdates = false;
            //    }
            //    catch (Exception ex)
            //    {
            //        Logging.LogError(ex, Constants.standardsLog);
            //    }
            //}


            


            /// <summary>
            /// Handles adding and removing of an AppConfig Enum
            /// </summary>
            /// <param name="myClass"></param>
            /// <param name="web"></param>
            /// <param name="AddEntries"></param>
            //public void AppConfigEntries(object myClass, SPWeb web, bool AddEntries = true)
            //{
            //    try
            //    {
            //        // setup SharePoint items to allow list item entry
            //        web.AllowUnsafeUpdates = true;
            //        SPList list = web.Lists[Constants.AppConfigListName];
            //        SPListItemCollection listItems = list.Items;

            //        // set our AppConfig class and get the Nested types within
            //        Type[] types = myClass.GetType().GetNestedTypes();
            //        // loop over each item in the class 
            //        foreach (Type type in types)
            //        {
            //            // check if we have an enum (should only be enums in AppConfig class)
            //            if (type.IsEnum)
            //            {
            //                // are we trying to add or remove entries?
            //                if (AddEntries)
            //                {

            //                    // loop over each Enum in the class
            //                    foreach (Enum item in Enum.GetValues(type))
            //                    {
            //                        Type itemType = item.GetType();
            //                        MemberInfo[] itemMembers = itemType.GetMembers();                                                                
            //                        // loop over every item in the particular Enum
            //                        for (int i = 0; i < itemMembers.Length; i++)
            //                        {
            //                            // ensure we are only getting the enum item members, not built-in items to enums   
            //                            if (itemMembers[i].Name == item.ToString())
            //                            {
            //                                // get all custom attributes from the particular Enum item
            //                                Object[] itemAttributes = itemMembers[i].GetCustomAttributes(false);
            //                                if (itemAttributes.Length > 0)
            //                                {
            //                                    #region AddEntries
            //                                    // Create our new List Item now
            //                                    SPListItem listItem = listItems.Add();

            //                                    // loop over each attribute for the item
            //                                    for (int j = 0; j < itemAttributes.Length; j++)
            //                                    {
            //                                        string attributeValue = string.Empty;
            //                                        bool attributeActive = default(bool);
            //                                        Guid attributeGuid = default(Guid);

            //                                        // try to cast attribute as a string IAttribute interface object
            //                                        Attributes.IAttribute<string> attribString = itemAttributes[j] as Attributes.IAttribute<string>;
            //                                        if (attribString != null)
            //                                        {
            //                                            // set our value
            //                                            attributeValue = attribString.Value;

            //                                            // get the SiteColumnID Guid for this attribute 
            //                                            // we have to know the Site Column to know what value to store in the correct column
            //                                            Attributes.IAttributeGuid attribeGuid = itemAttributes[j] as Attributes.IAttributeGuid;
            //                                            if (attribeGuid != null)
            //                                            {
            //                                                attributeGuid = attribeGuid.SiteColumnID;

            //                                                listItem[attributeGuid] = attributeValue;
            //                                            }
            //                                        }

            //                                        Attributes.IAttribute<bool> attribBool = itemAttributes[j] as Attributes.IAttribute<bool>;
            //                                        if (attribBool != null)
            //                                        {
            //                                            // set our value
            //                                            attributeActive = attribBool.Value;

            //                                            // get the SiteColumnID Guid for this attribute 
            //                                            Attributes.IAttributeGuid attribeGuid = itemAttributes[j] as Attributes.IAttributeGuid;
            //                                            if (attribeGuid != null)
            //                                            {
            //                                                attributeGuid = attribeGuid.SiteColumnID;

            //                                                listItem[attributeGuid] = attributeActive;
            //                                            }
            //                                        }
            //                                    }
            //                                    // update the list item
            //                                    listItem.Update();
            //                                    listItem = null;
            //                                    #endregion
            //                                }
            //                            }
            //                        }
            //                    }
            //                }
            //                else
            //                {
            //                    #region Remove Entries

            //                    bool removedItems = false;
            //                    string acModule = string.Empty;
            //                    string acGroup = string.Empty;
            //                    string acKey = string.Empty;

            //                    // loop over each Enum in the class
            //                    foreach (Enum item in Enum.GetValues(type))
            //                    {
            //                        Type itemType = item.GetType();
            //                        MemberInfo[] itemMembers = itemType.GetMembers();                                                                

            //                        // loop over every item in the particular Enum
            //                        for (int i = 0; i < itemMembers.Length; i++)
            //                        {
            //                            // ensure we are only getting the enum item members, not built-in items to enums   
            //                            if (itemMembers[i].Name == item.ToString())
            //                            {
            //                                // get all custom attributes from the particular Enum item
            //                                Object[] itemAttributes = itemMembers[i].GetCustomAttributes(false);
            //                                if (itemAttributes.Length > 0)
            //                                {
            //                                    for (int j = 0; j < itemAttributes.Length; j++)
            //                                    {
            //                                        Attributes.IAttributeGuid attribeGuid = itemAttributes[j] as Attributes.IAttributeGuid;
            //                                        if (attribeGuid != null)
            //                                        {
            //                                            Attributes.IAttribute<string> attribString = itemAttributes[j] as Attributes.IAttribute<string>;
            //                                            if (attribString != null)
            //                                            {
            //                                                if (attribeGuid.SiteColumnID == CoreColumnID.Module)
            //                                                {
            //                                                    acModule = attribString.Value;
            //                                                }
            //                                                if (attribeGuid.SiteColumnID == CoreColumnID.Group)
            //                                                {
            //                                                    acGroup = attribString.Value;
            //                                                }
            //                                                if (attribeGuid.SiteColumnID == CoreColumnID.Key)
            //                                                {
            //                                                    acKey = attribString.Value;
            //                                                }
            //                                            }
            //                                        }
            //                                    }
            //                                    // now remove all items
            //                                    removeAppConfigItems(web, acModule, acGroup, acKey);
            //                                    removedItems = true;
            //                                    break;                                                
            //                                }
            //                            }
            //                        }
            //                        if (removedItems)
            //                        {
            //                            break;
            //                        }                                    
            //                    }
            //                    #endregion                                
            //                }
            //            }
            //        }

            //        list.Update();
            //        web.AllowUnsafeUpdates = false;

            //        listItems = null;
            //        list = null;
            //    }
            //    catch (Exception ex)
            //    {
            //        Logging.LogError(ex, Constants.standardsLog);
            //    }
            //}


            public void DisplayAppConfigEntries(object myClass)
            {
                try
                {
                    // set our AppConfig class and get the Nested types within
                    Type[] types = myClass.GetType().GetNestedTypes();
                    // loop over each item in the class 
                    foreach (Type type in types)
                    {
                        // check if we have an enum (should only be enums in AppConfig class
                        if (type.IsEnum)
                        {
                            Console.WriteLine(string.Format("Type: {0}", type.Name));
                            // loop over each Enum in the class
                            foreach (Enum item in Enum.GetValues(type))
                            {
                                Console.WriteLine(string.Format("    Item: {0}", item.ToString()));
                                Type itemType = item.GetType();
                                MemberInfo[] itemMembers = itemType.GetMembers();
                                // loop over every item in the particular Enum
                                for (int i = 0; i < itemMembers.Length; i++)
                                {
                                    // ensure we are only getting the enum item members, not built-in items to enums   
                                    if (itemMembers[i].Name == item.ToString())
                                    {
                                        // get all custom attributes from the particular Enum item
                                        Object[] itemAttributes = itemMembers[i].GetCustomAttributes(false);
                                        if (itemAttributes.Length > 0)
                                        {
                                            // loop over each attribute for the item
                                            for (int j = 0; j < itemAttributes.Length; j++)
                                            {

                                                string attributeValue = string.Empty;
                                                bool attributeActive = default(bool);
                                                Guid attributeGuid = default(Guid);

                                                // try to cast attribute as a string IAttribute interface object
                                                Attributes.IAttribute<string> attribString = itemAttributes[j] as Attributes.IAttribute<string>;
                                                if (attribString != null)
                                                {
                                                    // set our value
                                                    attributeValue = attribString.Value;

                                                    // get the SiteColumnID Guid for this attribute 
                                                    // we have to know the Site Column to know what value to store in the correct column
                                                    Attributes.IAttributeGuid attribeGuid = itemAttributes[j] as Attributes.IAttributeGuid;
                                                    if (attribeGuid != null)
                                                    {
                                                        attributeGuid = attribeGuid.SiteColumnID;
                                                        Console.WriteLine(string.Format("        Item Value: {0}", attributeValue.ToString()));
                                                        Console.WriteLine(string.Format("        Item Guid: {0}", attributeGuid.ToString()));
                                                        Console.WriteLine("        -----------------------------------------------");
                                                    }
                                                }

                                                Attributes.IAttribute<bool> attribBool = itemAttributes[j] as Attributes.IAttribute<bool>;
                                                if (attribBool != null)
                                                {
                                                    // set our value
                                                    attributeActive = attribBool.Value;

                                                    // get the SiteColumnID Guid for this attribute 
                                                    Attributes.IAttributeGuid attribeGuid = itemAttributes[j] as Attributes.IAttributeGuid;
                                                    if (attribeGuid != null)
                                                    {
                                                        attributeGuid = attribeGuid.SiteColumnID;
                                                        Console.WriteLine(string.Format("        Item Value: {0}", attributeActive.ToString()));
                                                        Console.WriteLine(string.Format("        Item Guid: {0}", attributeGuid.ToString()));
                                                        Console.WriteLine("        -----------------------------------------------");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // implement error handling
                    throw ex;
                }

            }
        }
    }
    
}
